package br.com.pyramides.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;

import br.com.pyramides.dao.iface.IGenericDAO;
import br.com.pyramides.utils.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;

public abstract class GenericDAO<T, ID extends Serializable> implements IGenericDAO<T, ID>, Serializable {

    private static Log LOG = LogFactory.getLog(GenericDAO.class);

    @SuppressWarnings("unchecked")
    public GenericDAO() {
        this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }
    private Class<T> persistentClass;

    public Class<T> getPersistentClass() {
        return this.persistentClass;
    }

    @Override
    public void exclui(T entity) {
        Transaction transaction = null;
        Session session = null;
        try {
            session = new HibernateUtil().openSession();
            transaction = session.beginTransaction();
            session.delete(entity);
            transaction.commit();
        } catch (Exception ex) {
            transaction.rollback();
        } finally {
            session.clear();
            session.close();
        }
    }

    @Override
    public T buscaPeloID(ID id) {
        Transaction transaction = null;
        Session session = null;
        try {
            session = new HibernateUtil().openSession();
            transaction = session.beginTransaction();
            return (T) session.get(getPersistentClass(), id);
        } catch (Exception ex) {
            transaction.rollback();
        } finally {
            session.clear();
            session.close();
        }
        return null;
    }

    @Override
    public List<T> buscaTodos() {
        Transaction transaction = null;
        Session session = null;
        try {
            session = new HibernateUtil().openSession();
            transaction = session.beginTransaction();
            return session.createCriteria(persistentClass).list();
        } catch (Exception ex) {
            transaction.rollback();
        } finally {
            session.clear();
            session.close();
        }
        return null;
    }

    @Override
    public T salva(T entity) {
        Session session = null;
        Transaction transaction = null;
        try {
            session = new HibernateUtil().openSession();
            transaction = session.beginTransaction();
            session.save(entity);
            transaction.commit();
            return entity;
        } catch (Exception ex) {
            transaction.rollback();
        } finally {
            session.clear();
            session.close();
        }
        return null;
    }

    @Override
    public T atualiza(T entity) {
        Session session = null;
        Transaction transaction = null;
        try {
            session = new HibernateUtil().openSession();
            transaction = session.beginTransaction();
            session.update(entity);
            transaction.commit();
            return entity;
        } catch (Exception ex) {
            transaction.rollback();
        } finally {
            session.clear();
            session.close();
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<T> buscaListaPeloCriterio(Criterion... criterion) {
        Transaction transaction = null;
        Session session = null;
        try {
            session = new HibernateUtil().openSession();
            transaction = session.beginTransaction();
            Criteria crit = session.createCriteria(getPersistentClass());
            for (Criterion c : criterion) {
                crit.add(c);
            }
            List<T> list = crit.list();
            return list;
        } catch (Exception ex) {
            transaction.rollback();
        } finally {
            session.clear();
            session.close();
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    @Override
    public T buscaUmPeloCriterio(Criterion... criterion) {
        Transaction transaction = null;
        Session session = null;
        try {
            session = new HibernateUtil().openSession();
            transaction = session.beginTransaction();
            Criteria crit = session.createCriteria(getPersistentClass());
            for (Criterion c : criterion) {
                crit.add(c);
            }
            T entity = (T) crit.uniqueResult();
            return entity;
        } catch (Exception ex) {
            transaction.rollback();
        } finally {
            session.clear();
            session.close();
        }
        return null;
    }
}
